package io.github.kouleen.minecraft.plugin.redpacket.manager;

import io.github.kouleen.minecraft.core.lang.annotation.MinecraftPluginAutoInject;
import io.github.kouleen.minecraft.core.lang.annotation.MinecraftPluginComponent;
import io.github.kouleen.minecraft.plugin.redpacket.RedPacketPlugin;
import io.github.kouleen.minecraft.plugin.redpacket.entity.RedPacket;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.*;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scheduler.BukkitTask;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@MinecraftPluginComponent
public class RedPacketManager {

    private final Map<String, RedPacket> activeRedPackets = new ConcurrentHashMap<>();
    private final Map<String, BukkitTask> bukkitTaskMap = new ConcurrentHashMap<>();
    private Economy economy;
    @MinecraftPluginAutoInject
    private RedPacketPlugin plugin;

    /**
     * 初始化经济系统
     */
    public boolean setupEconomy() {
        Server server = plugin.getServer();
        if (server.getPluginManager().getPlugin("Vault") == null) {
            plugin.getLogger().severe("未找到Vault插件，经济功能无法使用!");
            return false;
        }

        RegisteredServiceProvider<Economy> rsp = server.getServicesManager().getRegistration(Economy.class);
        if (Objects.isNull(rsp)) {
            plugin.getLogger().severe("未找到经济服务提供商!");
            return false;
        }
        economy = rsp.getProvider();
        return Objects.nonNull(economy);
    }

    /**
     * 创建并发送红包
     */
    public boolean createRedPacket(Player sender, int totalAmount, int totalCount,
                                   String message, long expireSeconds, RedPacket.RedPacketType type) {
        // 验证参数
        if (totalAmount <= 0 || totalCount <= 0) {
            sender.sendMessage("§c红包金额和数量必须大于0!");
            return false;
        }

        // 验证金额不能太小
        if (totalAmount / totalCount < 1) {
            sender.sendMessage("§c单个红包金额不能小于1!");
            return false;
        }

        // 验证余额
        if (economy == null) {
            sender.sendMessage("§c经济系统未初始化，无法发送红包!");
            return false;
        }

        if (economy.getBalance(sender) < totalAmount) {
            sender.sendMessage("§c余额不足，无法发送红包!");
            return false;
        }

        // 扣钱
        economy.withdrawPlayer(sender, totalAmount);

        // 创建红包
        RedPacket redPacket = new RedPacket(sender.getUniqueId(),sender.getName(), totalAmount, totalCount, message, expireSeconds, type);
        BukkitTask bukkitTask = startExpirationChecker(expireSeconds);
        bukkitTaskMap.put(redPacket.getId(),bukkitTask);
        activeRedPackets.put(redPacket.getId(), redPacket);

        // 通知发送者
        sender.sendMessage("§a红包创建成功! 总金额: " + totalAmount + ", 总个数: " + totalCount);

        // 广播红包消息
        sendOnlinePlayerMessage(redPacket);
        return true;
    }

    /**
     * 广播红包消息
     */
    public TextComponent handleRedPacketMessage(RedPacket redPacket) {
        // 使用TextComponent创建可点击的消息
        TextComponent message = new TextComponent();

        TextComponent prefix = new TextComponent("玩家 ");
        prefix.setColor(ChatColor.YELLOW);

        TextComponent sender = new TextComponent(redPacket.getSender());
        sender.setColor(ChatColor.GOLD);
        sender.setBold(true);

        TextComponent middle = new TextComponent(" 发送了一个红包! ");
        middle.setColor(ChatColor.YELLOW);

        TextComponent claimButton = new TextComponent("[点击领取]");
        claimButton.setColor(ChatColor.GREEN);
        claimButton.setBold(true);
        claimButton.setClickEvent(new ClickEvent(
                ClickEvent.Action.RUN_COMMAND,
                "/redpacket claim " + redPacket.getId()
        ));
        claimButton.setHoverEvent(new HoverEvent(
                HoverEvent.Action.SHOW_TEXT,
                new ComponentBuilder("点击领取红包").color(ChatColor.AQUA).create()
        ));

        // 组合消息
        message.addExtra(prefix);
        message.addExtra(sender);
        message.addExtra(middle);
        message.addExtra(claimButton);
        if (redPacket.getMessage() != null && !redPacket.getMessage().isEmpty()) {
            // 添加红包消息（如果有）
            TextComponent msg = new TextComponent();
            msg.setText(" §7(" + redPacket.getMessage() + ")");
            msg.setColor(ChatColor.GRAY);
            message.addExtra(msg);
        }
        return message;
    }

    private void sendOnlinePlayerMessage(RedPacket redPacket){
        TextComponent message = handleRedPacketMessage(redPacket);
        // 发送消息给所有在线玩家并播放提示音
        for (Player player : Bukkit.getOnlinePlayers()) {
            player.spigot().sendMessage(message);
            player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 1.0f, 1.0f);
        }
    }

    /**
     * 玩家领取红包
     */
    public boolean claimRedPacket(Player player, String redPacketId) {
        RedPacket redPacket = activeRedPackets.get(redPacketId);
        if (redPacket == null) {
            player.sendMessage("§c红包不存在或已过期!");
            return false;
        }
        // 检查是否是发送者自己领取（可以根据配置决定是否允许）
        UUID uniqueId = redPacket.getUniqueId();
        OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uniqueId);
        if (offlinePlayer.getUniqueId().equals(player.getUniqueId())
                && !plugin.getConfig().getBoolean("allow-sender-claim", false)) {
            player.sendMessage("§c不能领取自己发送的红包!");
            return false;
        }
        // 领取红包
        double amount = redPacket.claim(player);
        if (amount <= 0) {
            player.sendMessage("§c领取失败，红包已被领完或你已领取过!");
            return false;
        }

        // 显示领取特效UI
        showClaimEffect(player, amount);

        // 给玩家加钱
        economy.depositPlayer(player, amount);

        // 发送领取成功消息
        player.sendMessage(String.format("§a恭喜你领取了 %s 的红包，获得 %.2f 金币!",
                offlinePlayer.getName(), amount));

        // 领取到最大金额时播放特殊音效 TODO 配置手气最佳是否广播
        if (isMaxAmount(redPacket, amount)) {
            player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1.0f, 1.0f);
            Bukkit.broadcastMessage(String.format("§e恭喜玩家 %s 领取了 %s 的手气最佳红包，获得 %.2f 金币!",
                    player.getName(), offlinePlayer.getName(), amount));
        }

        if(offlinePlayer.isOnline()){
            Player sender = offlinePlayer.getPlayer();
            // 通知发送者有人领取了红包
            sender.sendMessage(String.format("§e你的红包被 %s 领取了 %.2f 金币!",
                    player.getName(), amount));
        }
        // 检查红包是否已领完
        if (redPacket.isEmpty()) {
            activeRedPackets.remove(redPacketId);
            if(offlinePlayer.isOnline()){
                Player sender = offlinePlayer.getPlayer();
                sender.sendMessage("§a你的红包已被领完!");
            }
            BukkitTask bukkitTask = bukkitTaskMap.get(redPacketId);
            if (Objects.nonNull(bukkitTask) && !bukkitTask.isCancelled()) {
                bukkitTask.cancel();
                bukkitTaskMap.remove(redPacketId);
            }
        }
        return true;
    }

    /**
     * 检查是否为最大金额
     */
    private boolean isMaxAmount(RedPacket redPacket, double amount) {
        if (redPacket.getType() == RedPacket.RedPacketType.FIXED) {
            return false; // 固定金额没有手气最佳
        }
        double max = 0;
        for (double amt : redPacket.getAmounts()) {
            if (amt > max) {
                max = amt;
            }
        }
        return amount == max;
    }

    /**
     * 显示领取特效UI
     */
    private void showClaimEffect(Player player, double amount) {
        // 发送标题消息作为简单的UI特效
        player.sendTitle(
                "§6§l恭喜发财",
                String.format("§e获得 %.2f 金币", amount),
                10, 70, 20 // 淡入, 停留, 淡出时间(刻)
        );

        // 可以在这里添加更复杂的UI，如Inventory界面
        createRedPacketInventoryAnimation(player, amount);
    }

    /**
     * 创建红包领取动画Inventory界面 - 27格动态玻璃加载动画
     */
    private void createRedPacketInventoryAnimation(Player player, double amount) {
        // 创建一个27格的界面用于动画展示 (3行)
        Inventory animationInventory = Bukkit.createInventory(null, 27, "§e§l红包领取成功!");

        // 初始化所有槽位为空气
        for (int i = 0; i < 27; i++) {
            animationInventory.setItem(i, new ItemStack(Material.AIR));
        }
        // 设置中心展示物品(金币)
        ItemStack goldItem = new ItemStack(Material.GOLD_INGOT);
        // 显示给玩家
        player.openInventory(animationInventory);

        // 启动动态加载动画
        startGlassPaneAnimation27(animationInventory, player, goldItem);
        ItemMeta goldMeta = goldItem.getItemMeta();
        if (goldMeta != null) {
            goldMeta.setDisplayName("§e§l获得金币: §a§l" + String.format("%.2f", amount));
            List<String> lore = Arrays.asList(
                    "§7=====================",
                    "§6红包领取成功!",
                    "§7====================="
            );
            goldMeta.setLore(lore);
            goldItem.setItemMeta(goldMeta);
        }
    }

    /**
     * 启动27格玻璃板动态加载动画 - 首尾交互动态模式
     */
    private void startGlassPaneAnimation27(Inventory inventory, Player player, ItemStack goldItem) {
        // 不同颜色的玻璃板用于动画效果
        Material[] glassPanes = {
                Material.getMaterial("RED_STAINED_GLASS_PANE"),
                Material.getMaterial("ORANGE_STAINED_GLASS_PANE"),
                Material.getMaterial("YELLOW_STAINED_GLASS_PANE"),
                Material.getMaterial("GREEN_STAINED_GLASS_PANE"),
                Material.getMaterial("LIGHT_BLUE_STAINED_GLASS_PANE"),
                Material.getMaterial("PURPLE_STAINED_GLASS_PANE")
        };

        // 过滤掉null值确保安全
        glassPanes = Arrays.stream(glassPanes)
                .filter(Objects::nonNull)
                .toArray(Material[]::new);

        // 如果都没有找到合适的材料，降级到普通材料
        if (glassPanes.length == 0) {
            glassPanes = new Material[] {Material.STAINED_GLASS_PANE};
        }

        Material[] finalGlassPanes = glassPanes;

        Bukkit.getScheduler().runTaskTimer(plugin, new Runnable() {
            int step = 0;
            int colorIndex = 0;
            boolean fillingComplete = false;
            boolean waveEffect = false;
            int waveStep = 0;

            @Override
            public void run() {
                // 检查玩家是否仍然在线且界面仍然打开
                if (!player.isOnline() ||
                        !player.getOpenInventory().getTitle().equals("§e§l红包领取成功!")) {
                    Bukkit.getScheduler().cancelTask(Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, this, 0, 1));
                    return;
                }

                // 动画阶段1: 首尾交互填充
                if (!fillingComplete) {
                    // 定义首尾对应的槽位
                    int[] startSlots = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
                    int[] endSlots = {26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14};

                    if (step < startSlots.length) {
                        // 创建玻璃板物品
                        Material glassMaterial = finalGlassPanes[colorIndex % finalGlassPanes.length];
                        ItemStack glassItem = new ItemStack(glassMaterial);
                        ItemMeta meta = glassItem.getItemMeta();
                        if (meta != null) {
                            meta.setDisplayName(" ");
                            glassItem.setItemMeta(meta);
                        }

                        // 同时放置首尾对应的槽位
                        inventory.setItem(startSlots[step], glassItem.clone());
                        inventory.setItem(endSlots[step], glassItem.clone());

                        step++;
                        colorIndex++;
                    } else {
                        // 首尾填充完成，进入下一阶段
                        fillingComplete = true;
                        step = 0;
                    }
                }
                // 动画阶段2: 波浪效果
                else if (!waveEffect) {
                    // 定义波浪层（从外到内）
                    int[][] waveLayers = {
                            {0, 26},           // 最外层
                            {1, 25, 8, 18},    // 第二层
                            {2, 24, 7, 19},    // 第三层
                            {3, 23, 6, 20},    // 第四层
                            {4, 22, 5, 21},    // 第五层
                            {9, 17},           // 第六层
                            {10, 16},          // 第七层
                            {11, 15},          // 第八层
                            {12, 14},          // 第九层
                            {13}               // 中心
                    };

                    if (step < waveLayers.length) {
                        Material glassMaterial = finalGlassPanes[(colorIndex + step) % finalGlassPanes.length];
                        ItemStack glassItem = new ItemStack(glassMaterial);
                        ItemMeta meta = glassItem.getItemMeta();
                        if (meta != null) {
                            meta.setDisplayName(" ");
                            glassItem.setItemMeta(meta);
                        }

                        // 按层放置玻璃板
                        for (int slot : waveLayers[step]) {
                            inventory.setItem(slot, glassItem.clone());
                        }

                        step++;
                        colorIndex++;
                    } else {
                        // 波浪效果完成，进入下一阶段
                        waveEffect = true;
                        waveStep = 0;
                    }
                }
                // 动画阶段3: 中心汇聚效果
                else {
                    // 定义中心汇聚的槽位顺序（从外向内到中心）
                    int[] centerSlots = {13};

                    if (waveStep < centerSlots.length) {
                        // 在中心位置放置奖励物品
                        inventory.setItem(13, goldItem);
                        waveStep++;
                    } else {
                        // 动画完成，取消任务
                        Bukkit.getScheduler().cancelTask(Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, this, 0, 1));
                    }
                }
            }
        }, 3L, 3L); // 每3刻执行一次(0.15秒)

        // 6秒后自动关闭界面
        Bukkit.getScheduler().runTaskLater(plugin, () -> {
            if (player.getOpenInventory().getTitle().equals("§e§l红包领取成功!")) {
                player.closeInventory();
            }
        }, 120L); // 6秒 = 120刻
    }

    /**
     * 启动红包过期检查任务
     */
    public BukkitTask startExpirationChecker(long period) {
        BukkitScheduler bukkitScheduler = Bukkit.getScheduler();
        return bukkitScheduler.runTaskLaterAsynchronously(plugin, () -> {
            List<String> expiredIds = new ArrayList<>();
            for (RedPacket redPacket : activeRedPackets.values()) {
                OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(redPacket.getUniqueId());
                if (redPacket.isExpired()) {
                    expiredIds.add(redPacket.getId());
                    // 退还剩余金额给发送者
                    int remaining = redPacket.getRemainingAmount();
                    if (remaining > 0) {
                        economy.depositPlayer(offlinePlayer, remaining);
                        if (offlinePlayer.isOnline()) {
                            Player player = offlinePlayer.getPlayer();
                            player.sendMessage(String.format("§a你的红包已过期，剩余 %.2f 金币已退回!", remaining));
                        }
                    }
                }
            }
            // 移除过期红包
            for (String id : expiredIds) {
                activeRedPackets.remove(id);
            }
        }, 20 * period);
    }

    /**
     * 保存未领取的红包（插件禁用时调用）
     */
    public void saveUnclaimedRedPackets() {
        // 将未过期的红包保存到文件或数据库
        // 这里简化处理，只打印日志
        plugin.getLogger().info("保存了 " + activeRedPackets.size() + " 个未领取的红包");
    }

    public Map<String, RedPacket> getActiveRedPackets() {
        return activeRedPackets;
    }
}
